// Copyright (c) 2025 Inochi Amaoto

/* SPDX-License-Identifier: GPL-2.0 */

#ifndef __VHOST_VAPP_VIO_H__
#define __VHOST_VAPP_VIO_H__

#include "vhost-vapp.h"
#include "vio-entity.h"
#include "vio-mm.h"

static void vio_vapp_context_init(struct vio_vapp_context* ctx)
{
  vio_vapp_notify_queue_init(&ctx->queue);
  vio_mmap_entity_tree_init(&ctx->mtree);
}

__maybe_unused
static struct vio_vapp_context* vio_vapp_context_alloc(void)
{
  struct vio_vapp_context* ctx = kmalloc(sizeof(struct vio_vapp_context), GFP_KERNEL);

  if (!ctx)
    return ERR_PTR(-ENOMEM);

  vio_vapp_context_init(ctx);
  return ctx;
}

__maybe_unused
static void vio_vapp_context_deinit(struct vio_vapp_context* ctx)
{
  vio_vapp_notify_queue_destroy(&ctx->queue);
  vio_mmap_entity_tree_destroy(&ctx->mtree);
  return;
}

__maybe_unused
static void vio_vapp_context_free(struct vio_vapp_context* ctx)
{
  kvfree(ctx);
}

__maybe_unused
static void vhost_vapp_dev_start_work(struct vhost_vapp_dev* vapp)
{
  for (size_t i = 0; i < vapp->conf.multiqueues; i++)
    vhost_work_queue(&vapp->dev, &vapp->ddtqs[i].work);
}

__maybe_unused
static int vio_vapp_entity_send_packet(struct vio_vapp_entity* entity, struct vio_vapp_entity_tree* tree, struct vhost_vapp_dev* dev)
{
  struct vapp_send_data_packet* packets[VIO_VAPP_ENTITY_PKTS];
  int nr;
  int i;

  nr = vio_vapp_entity_split_packet(entity, tree, packets);
  if (nr < 0)
    goto failed;

  pr_info("packet: need to send %d packet\n", nr);

  for(i = 0; i < nr; i++)
    vapp_send_queue_add_tail(&dev->dqueue, &packets[i]->node);

  vhost_vapp_dev_start_work(dev);

  return 0;

 failed:
  return nr;
}

#endif // ! __VHOST_VAPP_VIO_H__
